#include "stdafx.h"
#include "winampin.h"
#include "globals.h"

void ProcessCommand(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
    switch(LOWORD(wparam))
		{
		case ID_FILE_PLAY:
			SendMessage(stMod.hMainWindow,WM_COMMAND,WINAMP_BUTTON2,0);
			break;
		case ID_FILE_PAUSE:
			SendMessage(stMod.hMainWindow,WM_COMMAND,WINAMP_BUTTON3,0);
			break;
		case ID_FILE_PREVTRACK:
			SendMessage(stMod.hMainWindow,WM_COMMAND,WINAMP_BUTTON1_SHIFT,0);
			break;
		case ID_FILE_NEXTTRACK:
			SendMessage(stMod.hMainWindow,WM_COMMAND,WINAMP_BUTTON5,0);
			break;
		case ID_FILE_FULLSCREEN:
			ToggleFullScreen();
			break;
		case ID_FILE_ABOUT:
			About(hwnd);
			break;
		case ID_FILE_SETTING:
			About(hwnd);
			break;
		case ID_ADDONSETTING_AUDIO:
			ShowAddOnAudio();
			break;
		case ID_ADDONSETTING_VIDEO:
			ShowAddOnVideo();
			break;
		case ID_FILE_RENDERSETTING:
			ShowRender();
			break;
		case ID_ADDONSETTING_AUDIOEFFECT:
			ShowAddOnAudioEffect();
			break;
		case ID_ADDONSETTING_VIDEOEFFECT:
			ShowAddOnVideoEffect();
			break;
		case ID_FILE_PROPERTIES:
			{
				if(!stInfo.ShowFilterProperty)
				{
					stInfo.ShowFilterProperty = TRUE;
					ShowWindow(CreateDialog(stMod.hDllInstance,MAKEINTRESOURCE(IDD_PROPERTIES),stInfo.hwnd,(DLGPROC)Propertiesproc),SW_SHOW);
				}
			}
			break;
		default:
			ProcessSkinMenu(LOWORD(wparam));			
	}
}


//Process the Skin menu selections
int ProcessSkinMenu(DWORD dwOption)
{
	int iIndex=0,iIndexMenuId=0;
	BOOL bShiftFlag = FALSE;
	SHORT stiStatus;
	char str[MAX_PATH];

	
    //Video Effect Menu
    if((dwOption >= (IDS_START+ID_EFFECT)) && (dwOption <= (IDS_END+ID_EFFECT+1)))
	{
		ZeroMemory(str,MAX_PATH);

		stiStatus = GetAsyncKeyState(VK_SHIFT);

		bShiftFlag = stiStatus & 0x8000;
				
		if(stGr.pIVideoEffect)
		{
			stGr.pIVideoEffect->SetOptions(dwOption-ID_EFFECT);
			if(bShiftFlag)
			{
				stGr.pIVideoEffect->SelectConfigure();
			}
		}

		sprintf_s(str,"%d",dwOption-ID_EFFECT);

		WritePrivateProfileString("Kannan","Effectno",str,"Plugin.ini");

		for(iIndex = (IDS_START+ID_EFFECT);iIndex <= (IDS_END+ID_EFFECT+1);iIndex++)
		{
			CheckMenuItem(stInfo.hMenuMainEffect,iIndex,MF_BYCOMMAND|MF_UNCHECKED);
		}
		CheckMenuItem(stInfo.hMenuMainEffect,dwOption,MF_BYCOMMAND|MF_CHECKED);
		return 1;
	}
	//Video External Effect Menu
	for(iIndex = 0 ;iIndex < stInfo.iExternalEffectCount ;iIndex++)
	{
		if(stExteff[iIndex].Menuid == dwOption)
		{
			if(!HIWORD(GetKeyState(VK_SHIFT)))
			{
				strcpy_s(str,stInfo.Path);
				strcat_s(str,"ExtEff\\");
				strcat_s(str,stExteff[iIndex].Path);
				WritePrivateProfileString("Kannan","ExtEffStr",stExteff[iIndex].Path,"Plugin.ini");
				CheckMenuItem(stInfo.hMenuEffect[INDEX_OF_EXEFF],stExteff[iIndex].Menuid,MF_BYCOMMAND|MF_CHECKED);
				if(stGr.pIVideoEffect)
				{
					stGr.pIVideoEffect->SetExtEff(str);
					stGr.pIVideoEffect->SetExtEff(stInfo.EnableExtEff);
				}
				for(iIndexMenuId = 0; iIndexMenuId < stInfo.iExternalEffectCount;iIndexMenuId++)
				{
					CheckMenuItem(stInfo.hMenuEffect[INDEX_OF_EXEFF],iIndexMenuId,MF_BYPOSITION|MF_UNCHECKED);
				}
				CheckMenuItem(stInfo.hMenuEffect[INDEX_OF_EXEFF],stExteff[iIndex].Menuid,MF_BYCOMMAND|MF_CHECKED);
				return 1;
			}
			else
			{
				stGr.pIVideoEffect->SetConfigure(stInfo.hwnd);
			}
		}
	}
	//Skin Menu
	for(iIndex = 0;iIndex < stInfo.iSkinCount;iIndex++)
	{
		if(stskm[iIndex].Menuid == dwOption)
		{
			WritePrivateProfileString("Kannan","Path",stskm[iIndex].Path,"Plugin.ini");
			LoadSkin();
			SendMessage(stInfo.hwnd,WM_NCPAINT,0,0);
			for(iIndexMenuId = 0 ;iIndexMenuId < stInfo.iSkinCount;iIndexMenuId++)
			{
				CheckMenuItem(stInfo.hMenuSkin,iIndexMenuId,MF_BYPOSITION|MF_UNCHECKED);
			}
			CheckMenuItem(stInfo.hMenuSkin,dwOption,MF_BYCOMMAND|MF_CHECKED);

			return 1;			
		}
	}
	return 0;	
}


void DisplayInfo(char * pstrBuf,char * pstrTitle)
{
	MessageBox(stMod.hMainWindow,pstrBuf,pstrTitle,0);
}

void ProcessKeyDown(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	double dRate;

	switch(LOWORD(wparam))
		{
		case VK_F1:
			About(hwnd);
			break;
		case VK_ADD:
			if(stGr.pIMediaPosition)
			{
				stGr.pIMediaPosition->get_Rate(&dRate);
				dRate += 0.10;
				stGr.pIMediaPosition->put_Rate(dRate);
			}
			break;
		case VK_SUBTRACT:
			if(stGr.pIMediaPosition)
			{
				stGr.pIMediaPosition->get_Rate(&dRate);
				dRate -= 0.10;
				stGr.pIMediaPosition->put_Rate(dRate);

			}
			break;
		case 'N':
			if(stGr.pIMediaPosition)
			{
				stGr.pIMediaPosition->put_Rate(1.0);
			}
			break;
		case VK_SPACE:
			SendMessage(stMod.hMainWindow,WM_COMMAND,WINAMP_BUTTON3,0);
			break;
		case VK_RETURN:
		case 'F':
			ToggleFullScreen();
			break;
		default:
			SendMessage(stMod.hMainWindow,msg,wparam,lparam);
		}
}


//Paint proc
int Paint(HWND hwnd)
{
	RECT r;
	HDC hdc;

	hdc=GetWindowDC(hwnd);
	GetWindowRect(hwnd,&r);

	StretchBlt(hdc,0,0,49,stInfo.CapHeight,stSk.mhdc,15,0,49,14,SRCCOPY);
	StretchBlt(hdc,49,0,(r.right-r.left)-64,stInfo.CapHeight,stSk.mhdc,66,0,13,14,SRCCOPY);
	StretchBlt(hdc,(r.right-r.left)-15,0,15,stInfo.CapHeight,stSk.mhdc,81,0,15,14,SRCCOPY);
	
	StretchBlt(hdc,0,stInfo.CapHeight,stInfo.Xborder,(r.bottom-r.top)-(stInfo.Yborder+stInfo.CapHeight),stSk.mhdc,0,16,6,171,SRCCOPY); 
	StretchBlt(hdc,(r.right-r.left)-stInfo.Xborder,stInfo.CapHeight,stInfo.Xborder,(r.bottom-r.top)-(stInfo.Yborder+stInfo.CapHeight),stSk.mhdc,8,16,5,171,SRCCOPY); 
	
	StretchBlt(hdc,0,(r.bottom-r.top)-stInfo.Yborder,49,stInfo.Yborder,stSk.mhdc,15,16,49,5,SRCCOPY);
	StretchBlt(hdc,49,(r.bottom-r.top)-stInfo.Yborder,(r.right-r.left)-64,stInfo.Yborder,stSk.mhdc,66,16,13,5,SRCCOPY);
	StretchBlt(hdc,(r.right-r.left)-16,(r.bottom-r.top)-stInfo.Yborder,16,stInfo.Yborder,stSk.mhdc,81,16,15,5,SRCCOPY);

	ReleaseDC(hwnd,hdc);

	return 0;
}


//Skin
void InitSkin(void)
{
	stInfo.hCursor = NULL;
	stSk.hbit = NULL;
	stSk.mhdc = NULL;
}
void UnloadSkin(void)
{
	if(stInfo.hCursor != NULL)
	{
        DestroyCursor(stInfo.hCursor);
	}
	if(stSk.hbit != NULL)
	{
        DeleteObject(stSk.hbit);
	}
	if(stSk.mhdc != NULL)
	{
        DeleteDC(stSk.mhdc);
	}
}
void LoadSkin(void)
{
	char path[MAX_PATH],str[MAX_PATH];
	bool bAutoSkinFailed = false;

	UnloadSkin();
	
	//check for the autoskin mode
	//Load the cursor
	if(stInfo.EnableAutoSkin)
	{
		//fill with zero
		ZeroMemory(str,MAX_PATH);
		//get the cursor path
		SendMessage(stMod.hMainWindow,WM_WA_IPC,(WPARAM)str,IPC_GETSKIN);
		//GetWindowText(stMod.hMainWindow,str,MAX_PATH);
		//MessageBox(0,str,"Tset",0);
		strcat_s(str,"\\Normal.cur");
		DestroyCursor(stInfo.hCursor);
		stInfo.hCursor = NULL;
		stInfo.hCursor = (HCURSOR)LoadCursorFromFile(str);
		//fails load the default one
		if(!stInfo.hCursor)
		{
			stInfo.hCursor = LoadCursor(stMod.hDllInstance,MAKEINTRESOURCE(IDC_ARROW1));
		}
	}
	else
	{
		//load the default one
		stInfo.hCursor = LoadCursor(0,IDC_ARROW);
	}
    
	//Fill with zero
	ZeroMemory(path,MAX_PATH);
	ZeroMemory(str,MAX_PATH);
	//check for autoskin mode
	if(stInfo.EnableAutoSkin)
	{
		if(stSk.hbit != NULL)
		{
			DeleteObject(stSk.hbit);
			stSk.hbit = NULL;
		}
		if(stSk.mhdc != NULL)
		{
			DeleteDC(stSk.mhdc);
			stSk.mhdc = NULL;
		}
		//Get the path of resource
		SendMessage(stMod.hMainWindow,WM_WA_IPC,(WPARAM)str,IPC_GETSKIN);
	    strcat_s(str,"\\avs.bmp");
		//Load from the file
		stSk.hbit = (HBITMAP)LoadImage(NULL,str,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);
		if(stSk.hbit == NULL)
		{
			bAutoSkinFailed = true;
		}
		else
		{
			GetObject(stSk.hbit,sizeof(BITMAP),&stSk.bmp);
			stSk.mhdc = CreateCompatibleDC(NULL);
			if(stSk.mhdc == NULL)
			{
				DeleteObject(stSk.hbit);
				bAutoSkinFailed = true;
			}
			else
			{
				DeleteObject(SelectObject(stSk.mhdc,stSk.hbit));
			}
		}
	}
	//Selected Skin
	if(!stInfo.EnableAutoSkin || bAutoSkinFailed == true)
	{
		GetPrivateProfileString("Kannan","Path",0,path,sizeof(path),"Plugin.ini");
		strcpy_s(str,stInfo.Path);
		strcat_s(str,"KannanSkin\\");
		strcat_s(str,path);
		stSk.hbit=(HBITMAP)LoadImage(NULL,str,IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);
		if(stSk.hbit == NULL)
		{
			stSk.hbit = LoadBitmap(stMod.hDllInstance,MAKEINTRESOURCE(IDB_MAIN));
		}
		GetObject(stSk.hbit,sizeof(BITMAP),&stSk.bmp);
		stSk.mhdc = CreateCompatibleDC(NULL);
		DeleteObject(SelectObject(stSk.mhdc,stSk.hbit));
	}
}

//Effect
void InitFilterMenu(void)
{
	int iIndexGlobal;
	int iIndexMenu;
	int iIndexCount;
	int iMaxCount;
	char *ptrRes;
	char *ptrBuf;
	char *next_token;
    
    //create effect menu
	stInfo.hMenuMainEffect = CreateMenu();

	{
		char str[MAX_PATH],strpath[MAX_PATH];
		WIN32_FIND_DATA fd;
		HANDLE fh;
		int iIndex;

		stInfo.iExternalEffectCount = 0;
		//Fill buf with 0
		ZeroMemory(str,MAX_PATH);
		ZeroMemory(strpath,MAX_PATH);
        
		//Get ExtEffect folder
		GetModuleFileName(stMod.hDllInstance,str,MAX_PATH);
		strncpy_s(strpath,str,(strrchr(str,'\\')-str)+1);
		strcat_s(strpath,"ExtEff\\");
		strcat_s(strpath,"*.dll");
        
		//Create the Exteff Menu
		stInfo.hMenuEffect[INDEX_OF_EXEFF] = CreateMenu();
		iIndex = 0;
		//start find the file
		fh = FindFirstFile(strpath,&fd);
		if(fh != INVALID_HANDLE_VALUE)
		{
            //Get the file name with full path
			strcpy_s(stExteff[iIndex].Path,fd.cFileName);
			ZeroMemory(str,MAX_PATH);
			//extract the filter name from the file path
			strncpy_s(str,stExteff[iIndex].Path,(strrchr(stExteff[iIndex].Path,'.')-stExteff[iIndex].Path));
			stExteff[iIndex].Menuid = ID_EXTEFF+iIndex;
			AppendMenu(stInfo.hMenuEffect[INDEX_OF_EXEFF],MF_STRING,stExteff[iIndex].Menuid,str);

			iIndex++;
			while(FindNextFile(fh,&fd) && iIndex < NO_OF_EXTEFF)
			{
				//make the menu
				strcpy_s(stExteff[iIndex].Path,fd.cFileName);
				ZeroMemory(str,MAX_PATH);
				strncpy_s(str,stExteff[iIndex].Path,(strrchr(stExteff[iIndex].Path,'.')-stExteff[iIndex].Path));
				stExteff[iIndex].Menuid=ID_EXTEFF+iIndex;
				AppendMenu(stInfo.hMenuEffect[INDEX_OF_EXEFF],MF_STRING,stExteff[iIndex].Menuid,str);
				iIndex++;
			}
			stInfo.iExternalEffectCount = iIndex;
		}
		if(!stInfo.iExternalEffectCount)
		{
			AppendMenu(stInfo.hMenuEffect[INDEX_OF_EXEFF],MF_STRING,ID_EXTEFF,"None");
		}
		
	}
    //attach the ExtEff menu to the main image eff menu
	AppendMenu(stInfo.hMenuMainEffect,MF_POPUP,(UINT)stInfo.hMenuEffect[INDEX_OF_EXEFF],PopupMenuTitle[INDEX_OF_EXEFF]);
	stInfo.hMenuEffect[INDEX_OF_EXEFF+1]=CreateMenu();
	iMaxCount = (IDS_END / MENU_MAX_COUNT) * MENU_MAX_COUNT;

	HRSRC findSRC = FindResource(stMod.hDllInstance,MAKEINTRESOURCE(IDR_EFFECTMENUTEXT),"TEXT");

	if(findSRC == NULL)
	{
		return;
	}

	HGLOBAL foundResource1 = LoadResource(stMod.hDllInstance,findSRC);

	if(foundResource1 ==  NULL)
	{
		return;
	}

	ptrRes = (char*)LockResource(foundResource1);

	ptrBuf = strtok_s(ptrRes,"\n\r",&next_token);
	for(iIndexGlobal = IDS_START,iIndexMenu = 1,iIndexCount = 1;iIndexGlobal <= iMaxCount;iIndexGlobal++,iIndexCount++)
	{
		if(iIndexCount > MENU_MAX_COUNT)
		{
            iIndexCount = 1;
            AppendMenu(stInfo.hMenuMainEffect,MF_POPUP,(UINT)stInfo.hMenuEffect[iIndexMenu],PopupMenuTitle[iIndexMenu]);
			iIndexMenu ++;
			stInfo.hMenuEffect[iIndexMenu]=CreateMenu();
		}
        
		AppendMenu(stInfo.hMenuEffect[iIndexMenu],MF_STRING,ID_EFFECT+iIndexGlobal,ptrBuf);
		ptrBuf = strtok_s(NULL,"\n\r",&next_token);
	}

	AppendMenu(stInfo.hMenuMainEffect,MF_POPUP,(UINT)stInfo.hMenuEffect[iIndexMenu],PopupMenuTitle[iIndexMenu]);

	for(iIndexGlobal = iMaxCount + 1;iIndexGlobal <= IDS_END ; iIndexGlobal++)
	{
		AppendMenu(stInfo.hMenuMainEffect,MF_STRING,ID_EFFECT+iIndexGlobal,ptrBuf);
		ptrBuf = strtok_s(NULL,"\n\r",&next_token);
	}
	//Append the end of the menu
	AppendMenu(stInfo.hMenuMainEffect,MF_STRING,ID_EFFECT+IDS_END+1,"No Effect");

	{
		int iIndex;
		char str[MAX_PATH];
		int flag = 1;

		ZeroMemory(str,MAX_PATH);
		GetPrivateProfileString("Kannan","Path",0,str,sizeof(str),"Plugin.ini");
		for(iIndex = 0;iIndex < stInfo.iSkinCount;iIndex++)
		{
			if(!strcmp(stskm[iIndex].Path,str))
			{
				flag = 0;
				CheckMenuItem(stInfo.hMenuSkin,stskm[iIndex].Menuid,MF_BYCOMMAND|MF_CHECKED);
			}
		}
		if(flag)
		{
			CheckMenuItem(stInfo.hMenuSkin,0,MF_BYPOSITION|MF_CHECKED);
		}
	}
}

//Toggle Fullscreen
void ToggleFullScreen(void)
{
	long ax,ay,s;
	RECT r,r1;
	double d;
	HWND hwnd;
	//check the videorender is exists
	if(stGr.pIVideoWindow)
	{
        //check the video effect is enabled	
		if(stInfo.EnableEffect)
		{
			//check the whether already in fullscreen
			if(!stInfo.FullScreenFlag)
			{
				//try to set the fullscreen mode
				stGr.pIVideoWindow->get_MessageDrain(&stInfo.hwnddrain);
				stGr.pIVideoWindow->put_MessageDrain((OAHWND)stInfo.hwnd);
				GetWindowRect(GetDesktopWindow(),&r);
				r1=r;
				stInfo.hwndfull=CreateWindowEx(0,FULLCLASSNAME,"FullScreen",WS_POPUP|WS_VISIBLE,0,0,r.right,r.bottom,0,0,stMod.hDllInstance,0);
				//stInfo.hwndfull=FindWindow("Internet Explorer_Server","");
				ShowWindow(stInfo.hwndfull,SW_SHOW);
				stGr.pIVideoWindow->put_Owner((OAHWND)stInfo.hwndfull);
				if(stInfo.EnableAspectRatio)
				{
					if(stGr.pIBasicVideo)
					{
						stGr.pIBasicVideo->GetVideoSize(&ax,&ay);
						d=(float)ay/(float)(ax-ay);
						s=(long)((((float)(ax-ay)/(float)ax)*(float)r1.right)*d);
						if(s>r1.bottom)
						{
							d=(float)ax/(float)(ax-ay);
							s=(long)((((float)(ax-ay)/(float)ay)*(float)r1.bottom)*d);
							r.right=s;
						}
						else
							r.bottom=s;
					
						r.top=r.left =0;
						if((r1.bottom-r.bottom)>0)
						{
							s=(long)abs(r.bottom-r1.bottom);
							r.bottom=(long)(r1.bottom-s/2);
							r.top=(long)(s/2);
						}
						if((r1.right-r.right)>0)
						{
							s=(long)abs(r.right-r1.right);
							r.left=(long)(s/2);
							r.right=(long)(r1.right-s/2);
						}

					}
				}
				stGr.pIVideoWindow->put_WindowStyleEx(WS_EX_TOPMOST);
				stGr.pIVideoWindow->get_Owner((OAHWND*)&hwnd);
				stGr.pIVideoWindow->SetWindowPosition(r.left,r.top,r.right-r.left,r.bottom-r.top);
				GetWindowRect(GetDesktopWindow(),&r);
				SetWindowPos(hwnd,HWND_TOPMOST,0,0,r.right,r.bottom,SWP_SHOWWINDOW);
				SetFocus(hwnd);
				stInfo.FullScreenFlag=TRUE;
				
			}
			else
			{
				//switch off the fullscreen mode
				stGr.pIVideoWindow->put_MessageDrain(stInfo.hwnddrain);
				stInfo.FullScreenFlag = FALSE;
				ShowWindow(stInfo.hwndfull,SW_HIDE);
				stGr.pIVideoWindow->put_Owner((OAHWND)stInfo.hwnd);
				
				DestroyWindow(stInfo.hwndfull);
				
				GetClientRect(stInfo.hwnd,&r);
				SendMessage(stInfo.hwnd,WM_SIZE,0,0);
				UpdateWindow(stInfo.hwnd);
				SetFocus(stInfo.hwnd);
			}
		}
		else
		{
			//normal fullscreen mode
			stGr.pIVideoWindow->get_FullScreenMode(&s);
			if(s==OAFALSE)
			{
				stGr.pIVideoWindow->get_MessageDrain(&stInfo.hwnddrain);
				stGr.pIVideoWindow->put_MessageDrain((OAHWND)stInfo.hwnd);
			//	stGr.pIVideoWindow->HideCursor(OAFALSE);
				stGr.pIVideoWindow->put_FullScreenMode(OATRUE);
				
			}
			else
			{
				////switch off the normal fullscreen mode
				stGr.pIVideoWindow->put_MessageDrain(stInfo.hwnddrain);
				stGr.pIVideoWindow->put_FullScreenMode(OAFALSE);
				UpdateWindow(stInfo.hwnd);
				SetFocus(stInfo.hwnd);
			}
		}
	}
}

HRESULT EnumFilters (IGraphBuilder *pGraph, HWND hList) 
{
    IEnumFilters *pEnum = NULL;
    IBaseFilter *pFilter;
    ULONG cFetched;

    HRESULT hr = pGraph->EnumFilters(&pEnum);
    if (FAILED(hr)) return hr;

    while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
    {
        FILTER_INFO FilterInfo;
		ISpecifyPropertyPages *pProp = NULL;
		
        hr = pFilter->QueryFilterInfo(&FilterInfo);
        if (FAILED(hr))
        {
            MessageBox(NULL, TEXT("Could not get the filter info"),
                TEXT("Error"), MB_OK | MB_ICONERROR);
            continue;  // Maybe the next one will work.
        }

		hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
		if(hr == S_OK)
		{
			char szName[MAX_FILTER_NAME];
			WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
				MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);

			SendMessage(hList,LB_ADDSTRING,0,(LPARAM)szName);
	
			pProp->Release();
		}

        // The FILTER_INFO structure holds a pointer to the Filter Graph
        // Manager, with a reference count that must be released.
        if (FilterInfo.pGraph != NULL)
        {
            FilterInfo.pGraph->Release();
        }
        pFilter->Release();
    }

    pEnum->Release();
    return S_OK;
}
HRESULT ShowFilterPropertyPage(IBaseFilter *pFilter , HWND hwnd)
{
	/* Obtain the filter's IBaseFilter interface. (Not shown) */
	ISpecifyPropertyPages *pProp;
	HRESULT hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pProp);
	if (SUCCEEDED(hr)) 
	{
		// Get the filter's name and IUnknown pointer.
		FILTER_INFO FilterInfo;
		hr = pFilter->QueryFilterInfo(&FilterInfo); 
		IUnknown *pFilterUnk;
		pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);

		// Show the page. 
		CAUUID caGUID;
		pProp->GetPages(&caGUID);
		pProp->Release();
		OleCreatePropertyFrame(
			hwnd,                   // Parent window
			0, 0,                   // Reserved
			FilterInfo.achName,     // Caption for the dialog box
			1,                      // Number of objects (just the filter)
			&pFilterUnk,            // Array of object pointers. 
			caGUID.cElems,          // Number of property pages
			caGUID.pElems,          // Array of property page CLSIDs
			0,                      // Locale identifier
			0, NULL                 // Reserved
		);

		// Clean up.
		pFilterUnk->Release();
		FilterInfo.pGraph->Release(); 
		CoTaskMemFree(caGUID.pElems);
	}
	return hr;
}
HRESULT ShowFilterPropertyPageByName(IGraphBuilder *pGraph ,const char *ptName, HWND hwnd)
{
	IEnumFilters *pEnum = NULL;
    IBaseFilter *pFilter;
    ULONG cFetched;

    HRESULT hr = pGraph->EnumFilters(&pEnum);
    if (FAILED(hr)) return hr;

    while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
    {
        FILTER_INFO FilterInfo;
				
        hr = pFilter->QueryFilterInfo(&FilterInfo);
        if (FAILED(hr))
        {
            MessageBox(NULL, TEXT("Could not get the filter info"),
                TEXT("Error"), MB_OK | MB_ICONERROR);
            continue;  // Maybe the next one will work.
        }

		char szName[MAX_FILTER_NAME];
		WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName,
				MAX_FILTER_NAME, szName, MAX_FILTER_NAME, 0, 0);

		if(!strcmp(ptName,szName))
		{
            ShowFilterPropertyPage(pFilter,hwnd);
		}

        // The FILTER_INFO structure holds a pointer to the Filter Graph
        // Manager, with a reference count that must be released.
        if (FilterInfo.pGraph != NULL)
        {
            FilterInfo.pGraph->Release();
        }
        pFilter->Release();
    }

    pEnum->Release();
    return S_OK;
}
void InstallFilter(void)
{
	char strModuleName[MAX_PATH],strFilePath[MAX_PATH],strTempSrc[MAX_PATH];
	char strTempDest[MAX_PATH];
	
	ZeroMemory(strModuleName,MAX_PATH);
	ZeroMemory(strFilePath,MAX_PATH);
	ZeroMemory(strTempSrc,MAX_PATH);
	ZeroMemory(strTempDest,MAX_PATH);

	GetModuleFileName(stMod.hDllInstance,strModuleName,MAX_PATH);
	GetFullPathName(strModuleName,MAX_PATH,strFilePath,0);
	ZeroMemory(strModuleName,MAX_PATH);
	strncpy_s(strModuleName,strFilePath,strrchr(strFilePath,'\\') - strFilePath + 1);

    strcpy_s(strTempSrc,strModuleName);
	strcat_s(strTempSrc,KANNANS_EFFECTFILTER_FILENAME);

	ZeroMemory(strFilePath,MAX_PATH);
	GetSystemDirectory(strFilePath,MAX_PATH);

	strcpy_s(strTempDest,strFilePath);
	strcat_s(strTempDest,"\\");
	strcat_s(strTempDest,KANNANS_EFFECTFILTER_FILENAME);

	CopyFile(strTempSrc,strTempDest,FALSE);
	RegisterDll(strTempDest,TRUE);

	/*ZeroMemory(strTempSrc,MAX_PATH);
	strcpy_s(strTempSrc,strModuleName);
	strcat_s(strTempSrc,KANNANS_RENDERFILTER_FILENAME);

	ZeroMemory(strTempDest,MAX_PATH);
	strcpy_s(strTempDest,strFilePath);
	strcat_s(strTempDest,"\\");
	strcat_s(strFilePath,KANNANS_RENDERFILTER_FILENAME);

	CopyFile(strTempSrc,strTempDest,FALSE);
	RegisterDll(strTempDest,TRUE);*/

	//{
	//	MessageBox( NULL, "Automatic Filter Registration F, "Error", MB_OK | MB_ICONINFORMATION );
	//	//LPVOID strBuf = NULL;
	//	//FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,
	//	//GetLastError(),LANG_USER_DEFAULT,(LPSTR)&strBuf,0,NULL);
	//	//// Display the string.
	//	//MessageBox( NULL, (LPCTSTR)strBuf, "Error", MB_OK | MB_ICONINFORMATION );
 // //      
	//	//// Free the buffer.
	//	//LocalFree(strBuf);
	//}
	
}
void ShowAddOnAudio(void)
{
	if(stGr.pAudioDecoderFilter)
	{
        ShowFilterPropertyPage(stGr.pAudioDecoderFilter,stInfo.hwnd);
	}
}
void ShowAddOnVideo(void)
{
	if(stGr.pVideoDecoderFilter)
	{
        ShowFilterPropertyPage(stGr.pVideoDecoderFilter,stInfo.hwnd);
	}
}
void ShowRender(void)
{
	if(stGr.pVideoRenderFilter)
	{
        ShowFilterPropertyPage(stGr.pVideoRenderFilter,stInfo.hwnd);
	}
}
void ShowAddOnAudioEffect(void)
{
	if(stGr.pAudioEffectFilter)
	{
        ShowFilterPropertyPage(stGr.pAudioEffectFilter,stInfo.hwnd);
	}
}
void ShowAddOnVideoEffect(void)
{
	if(stGr.pVideoEffectFilter)
	{
        ShowFilterPropertyPage(stGr.pVideoEffectFilter,stInfo.hwnd);
	}
}
void SelectAudioEffectFilter(void)
{
	switch(stInfo.iAudioEffectMethod)
	{
	case AUDIOEFFECT_FFDSHOW:
		{
			CoCreateInstance(CLSID_FFDShowAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
		}
		break;
	case AUDIOEFFECT_MATRIXMIXER:
		{
			CoCreateInstance(CLSID_MatrixMixer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			if(!stGr.pAudioEffectFilter)
			{
				InitThirdFilter(TRUE);
				CoCreateInstance(CLSID_MatrixMixer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			}
			
		}
		break;
	case AUDIOEFFECT_INTER:
		{
			CoCreateInstance(CLSID_InterAudioEffect,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			if(!stGr.pAudioEffectFilter)
			{
				InitThirdFilter(TRUE);
				CoCreateInstance(CLSID_InterAudioEffect,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			}
		}
		break;
	case AUDIOEFFECT_DCDSP:
		{
			CoCreateInstance(CLSID_DCDSPAudioEffect,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			if(!stGr.pAudioEffectFilter)
			{
				InitThirdFilter(TRUE);
				CoCreateInstance(CLSID_DCDSPAudioEffect,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			}
		}
		break;
	default:
		{
			//create the filter for the dsp effect
			CoCreateInstance(CLSID_DefaultAudioEffectFilter,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			//if failes try to correct
			if(!stGr.pAudioEffectFilter)
			{
				InstallFilter();
				//retry to make dsp filter
				CoCreateInstance(CLSID_DefaultAudioEffectFilter,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioEffectFilter);
			}
			//Set the dsp effect	
			if(stGr.pAudioEffectFilter)
			{
				stGr.pAudioEffectFilter->QueryInterface(IID_DefaultAudioeffect,(void**)&stGr.pIAudioEffect);
				if(stGr.pIAudioEffect)
				{
					stGr.pIAudioEffect->SetDspfunction(&stAmod);
				}
			}
		}
	}
}
void SelectVideoEffectFilter(void)
{
	//create the colorspace filter
	CoCreateInstance(CLSID_Colour,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pColorSpaceFilter);
    //add to the pool
	if(stGr.pColorSpaceFilter)
	{
		stGr.pGraphFilter->AddFilter(stGr.pColorSpaceFilter,L"ColorSpace");
	}

	switch(stInfo.iVideoEffectMethod)
	{
	case VIDEOEFFECT_FFDSHOW:
		{
			//create the Image Effect filter
			CoCreateInstance(CLSID_FFDShowVideoEffect,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoEffectFilter);
		}
		break;
	default:
		{
			//create the Image Effect filter
			CoCreateInstance(CLSID_DefaultVideoEffectFilter,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoEffectFilter);
			//if fails try to correct	
			if(!stGr.pVideoEffectFilter)
			{
				InstallFilter();
				//retry
				CoCreateInstance(CLSID_DefaultVideoEffectFilter,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoEffectFilter);
		
			}
			//query the effect interface
			if(stGr.pVideoEffectFilter)
			{
				stGr.pVideoEffectFilter->QueryInterface(IID_DefaultVideoEffectInterface,(void**)&stGr.pIVideoEffect);
			}
			//try to set the options
			if(stGr.pIVideoEffect)
			{
				char strTemp[MAX_PATH],strExeffPath[MAX_PATH];
				//fill the buf with zero
				ZeroMemory(strExeffPath,MAX_PATH);
				ZeroMemory(strTemp,MAX_PATH);

				//set the options
				stGr.pIVideoEffect->SetOptions(GetPrivateProfileInt("Kannan","Effectno",0,"Plugin.ini"));
				stGr.pIVideoEffect->SetSmooth(stInfo.EnableSmooth);

				strcpy_s(strExeffPath,stInfo.Path);
				strcat_s(strExeffPath,"ExtEff\\");
				GetPrivateProfileString("Kannan","ExtEffStr",NULL,strTemp,MAX_PATH,"Plugin.ini");
				strcat_s(strExeffPath,strTemp);
				//set the ext effect
				stGr.pIVideoEffect->SetExtEff(strExeffPath);
				stGr.pIVideoEffect->SetExtEff(stInfo.EnableExtEff);
				
			}
		}
	}
}
void SelectDecodeFilter(void)
{
	switch(stInfo.iDecodeMethod)
	{
	case ADDON_FFDSHOW:
		{
			//ffDShow
			//IID_IffDecoder;
			CoCreateInstance(CLSID_FFDShowAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
			CoCreateInstance(CLSID_FFDShowVideoDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
		}
		break;
	case ADDON_GPLMPEG:
		{
			//GPL MPEG1/2
			//IID_IMpeg2DecFilter
			CoCreateInstance(CLSID_AC3AudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
			CoCreateInstance(CLSID_GPLMPEG12Decoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
			if(!stGr.pAudioDecoderFilter || !stGr.pVideoDecoderFilter)
			{
				if(stGr.pAudioDecoderFilter)
				{
					stGr.pAudioDecoderFilter->Release();
					stGr.pAudioDecoderFilter = NULL;
				}
				if(stGr.pVideoDecoderFilter)
				{
					stGr.pVideoDecoderFilter->Release();
					stGr.pVideoDecoderFilter = NULL;
				}
				InitThirdFilter(TRUE);
				CoCreateInstance(CLSID_AC3AudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
				CoCreateInstance(CLSID_GPLMPEG12Decoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
			}
		}
		break;
	case ADDON_LIGOS:
		{
			//Ligos
			CoCreateInstance(CLSID_LigosMPEGAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
			CoCreateInstance(CLSID_LigosMPEGVideoDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
		}
		break;
	case ADDON_NERO:
		{
			//Nero
			CoCreateInstance(CLSID_NeroAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
			CoCreateInstance(CLSID_NeroVideoDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
		}
		break;
	case ADDON_FRAUNHOFER:
		{
			//Fraunhofer
			CoCreateInstance(CLSID_FraunhoferAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
			CoCreateInstance(CLSID_FraunhoferVideoDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
			if(!stGr.pAudioDecoderFilter || !stGr.pVideoDecoderFilter)
			{
				if(stGr.pAudioDecoderFilter)
				{
					stGr.pAudioDecoderFilter->Release();
					stGr.pAudioDecoderFilter = NULL;
				}
				if(stGr.pVideoDecoderFilter)
				{
					stGr.pVideoDecoderFilter->Release();
					stGr.pVideoDecoderFilter = NULL;
				}
				InitThirdFilter(TRUE);
				CoCreateInstance(CLSID_FraunhoferAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
				CoCreateInstance(CLSID_FraunhoferVideoDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
			}
		}
		break;
	case ADDON_INTER:
		{
			//Inter video
			CoCreateInstance(CLSID_InterAudioDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pAudioDecoderFilter);
			CoCreateInstance(CLSID_InterVideoDecoder,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoDecoderFilter);
		}
		break;
	}
}
void SelectRenderFilter(void)
{
	//create the VideoRenderer
	switch(stInfo.iSetRenderMethod)
	{
	case RENDER_DEFAULT:
		{
			CoCreateInstance(CLSID_VideoRenderer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoRenderFilter);
		}
		break;
	case RENDER_VMR:
		{
			CoCreateInstance(CLSID_VideoRendererDefault,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoRenderFilter);
		}
		break;
	case RENDER_VMRMIXING:
		{
			CoCreateInstance(CLSID_VideoMixingRenderer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoRenderFilter);
		}
		break;
	case RENDER_ADVRENDER:
		{
			CoCreateInstance(CLSID_AdvVideoRenderer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoRenderFilter);
			if(stGr.pVideoRenderFilter == NULL)
			{
				MessageBox(0,"Test","Test",0);
				CoCreateInstance(CLSID_VideoRenderer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoRenderFilter);
			}
		}
		break;
	default:
		{
			CoCreateInstance(CLSID_VideoRenderer,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&stGr.pVideoRenderFilter);
		}
	}
}
void InitThirdFilter(BOOL bFlag)
{
	char strModuleName[MAX_PATH],strFolderPath[MAX_PATH];
	char strFileName[MAX_PATH];
	WIN32_FIND_DATA fd;
	HANDLE fh;

	//Fill buf with 0
	ZeroMemory(strModuleName,MAX_PATH);
	ZeroMemory(strFolderPath,MAX_PATH);

	//Get ExtEffect folder
	GetModuleFileName(stMod.hDllInstance,strModuleName,MAX_PATH);
	strncpy_s(strFolderPath,strModuleName,(strrchr(strModuleName,'\\') - strModuleName) + 1);
	strcat_s(strFolderPath,"Third\\");
	strcat_s(strFolderPath,"*.ax");

	//start find the file
	fh = FindFirstFile(strFolderPath,&fd);

	ZeroMemory(strFolderPath,MAX_PATH);

	//Get ExtEffect folder
	GetModuleFileName(stMod.hDllInstance,strModuleName,MAX_PATH);
	strncpy_s(strFolderPath,strModuleName,(strrchr(strModuleName,'\\') - strModuleName) + 1);
	strcat_s(strFolderPath,"Third\\");

	if(fh != INVALID_HANDLE_VALUE)
	{
		//Get the file name with full path
		ZeroMemory(strFileName,MAX_PATH);
		strcpy_s(strFileName,strFolderPath);
		strcat_s(strFileName,fd.cFileName);
		RegisterDll(strFileName,bFlag);

		while(FindNextFile(fh,&fd))
		{
			//make the menu
			ZeroMemory(strFileName,MAX_PATH);
			strcpy_s(strFileName,strFolderPath);
			strcat_s(strFileName,fd.cFileName);
			RegisterDll(strFileName,bFlag);
		}
	}
}